package com.xzy.spring.ccc;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ResolvableType;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 如何根据ResolvableType解析泛型信息
 *
 * @author xzy.xiao
 * @date 2023/3/10  13:56
 */
@Slf4j
class GenericClass extends MySuperClass implements Comparable<Integer>, Serializable {
    public Integer[] integerArray;
    public List<Integer> integerList;
    public Map<String, List<Integer>> string2IntegerListMap;
    public Map<Map<Integer, String>, Map<String, List<Integer>>> badMap;

    @Override
    public int compareTo(Integer o) {
        return 0;
    }

    public static void main(String[] args) throws NoSuchFieldException {
        log.info("========== 获取泛型数组的元素类型 ==========");
        test0();

        log.info("========== 获取泛型的实际类型 ==========");
        test1();

        log.info("========== 获取类型实现的接口 ==========");
        test2();

        log.info("========== 获取指定嵌套的类型 ==========");
        test3();

        log.info("========== 获取原始类型 ==========");
        test4();

        log.info("========== 获取父类型 ==========");
        test5();

        log.info("========== 获取Type ==========");
        test6();

        log.info("========== 判断当前实例是否包含泛型参数 ==========");
        test7();

        log.info("========== 判断当前实例是否为数组 ==========");
        test8();

        log.info("========== 判断指定类型是否可以转换为当前类型 ==========");
        test9();

        log.info("========== 获取当前实例解析出的Class ==========");

        test10();
    }

    /**
     * 获取当前实例解析出的Class
     *
     * @throws NoSuchFieldException -
     */
    private static void test10() throws NoSuchFieldException {
        Class<?> clazz0 = ResolvableType.forClass(GenericClass.class).resolve();
        log.info("获取当前实例解析出的Class：class GenericClass => {}", clazz0);

        Class<?> clazz1 = ResolvableType.forField(GenericClass.class.getField("integerList")).resolveGeneric(0);
        log.info("获取当前实例解析出的Class：List<Integer> => {}", clazz1);

        Class<?> clazz2 = ResolvableType.forField(GenericClass.class.getField("string2IntegerListMap")).resolveGeneric(0);
        log.info("获取当前实例解析出的Class：Map<String, List<Integer>>中的String => {}", clazz2);

        Class<?> clazz3 = ResolvableType.forField(GenericClass.class.getField("string2IntegerListMap")).resolveGeneric(1);
        log.info("获取当前实例解析出的Class：Map<String, List<Integer>>中的List<Integer> => {}", clazz3);
    }

    /**
     * 判断指定类型是否可以转换为当前类型
     */
    private static void test9() {
        log.info("判断指定类型是否可以转换为当前类型：GenericClass is MySuperClass ? => {}", ResolvableType.forClass(MySuperClass.class).isAssignableFrom(GenericClass.class));
        log.info("判断指定类型是否可以转换为当前类型：GenericClass is Comparable ? => {}", ResolvableType.forClass(Comparable.class).isAssignableFrom(GenericClass.class));
        log.info("判断指定类型是否可以转换为当前类型：GenericClass is Serializable ? => {}", ResolvableType.forClass(Serializable.class).isAssignableFrom(GenericClass.class));
        log.info("判断指定类型是否可以转换为当前类型：GenericClass is String ? => {}", ResolvableType.forClass(String.class).isAssignableFrom(GenericClass.class));
    }

    /**
     * 判断当前实例是否为数组
     *
     * @throws NoSuchFieldException -
     */
    private static void test8() throws NoSuchFieldException {
        log.info("判断当前实例是否为数组：Integer[] => {}", ResolvableType.forField(GenericClass.class.getField("integerArray")).isArray());
        log.info("判断当前实例是否为数组：Map<String, List<Integer>> => {}", ResolvableType.forField(GenericClass.class.getField("string2IntegerListMap")).isArray());
    }

    /**
     * 判断当前实例是否包含泛型参数
     */
    private static void test7() {
        log.info("判断当前实例是否包含泛型参数：class String => {}", ResolvableType.forClass(String.class).hasGenerics());
        log.info("判断当前实例是否包含泛型参数：interface List<E> extends Collection<E> => {}", ResolvableType.forClass(List.class).hasGenerics());
    }

    /**
     * 获取Type
     *
     * @throws NoSuchFieldException -
     */
    private static void test6() throws NoSuchFieldException {
        log.info("获取Type：{}", ResolvableType.forClass(GenericClass.class).getType());
        log.info("获取Type：{}", ResolvableType.forField(GenericClass.class.getField("integerArray")).getType());
        log.info("获取Type：{}", ResolvableType.forField(GenericClass.class.getField("string2IntegerListMap")).getType());
    }

    /**
     * 获取父类型
     */
    private static void test5() {
        ResolvableType superType = ResolvableType.forClass(GenericClass.class).getSuperType();
        log.info("获取父类型：class GenericClass extends MySuperClass => {}", superType);
    }

    /**
     * 获取原始类型
     *
     * @throws NoSuchFieldException -
     */
    private static void test4() throws NoSuchFieldException {
        ResolvableType fieldType = ResolvableType.forField(GenericClass.class.getDeclaredField("string2IntegerListMap"));
        log.info("获取原始类型：Map<String, List<Integer>> => {}", fieldType.getRawClass());
    }

    /**
     * 获取指定嵌套的类型
     *
     * @throws NoSuchFieldException -
     */
    private static void test3() throws NoSuchFieldException {
        // 嵌套级别从 1 开始
        ResolvableType fieldType = ResolvableType.forField(GenericClass.class.getDeclaredField("badMap"));

        /*
         * Map<Map<Integer, String>, Map<String, List<Integer>>>：
         *
         * Map<Map,Map>                                           第一层
         *          |
         *          |---> Map<String, List>                       第二层
         *                            |
         *                            |---> List<Integer>         第三层
         */
        log.info("获取指定嵌套的类型：Map<Map<Integer, String>, Map<String, List<Integer>>>的第一层 => {}", fieldType.getNested(1));
        log.info("获取指定嵌套的类型：Map<Map<Integer, String>, Map<String, List<Integer>>>的第二层 => {}", fieldType.getNested(2));
        log.info("获取指定嵌套的类型：Map<Map<Integer, String>, Map<String, List<Integer>>>的第三层 => {}", fieldType.getNested(3));
    }

    /**
     * 获取类型实现的接口
     */
    private static void test2() {
        ResolvableType[] implInterfaces = ResolvableType.forClass(GenericClass.class).getInterfaces();
        log.info("获取类型实现的接口：class GenericClass implements Comparable<Integer>, Serializable => {}", Arrays.toString(implInterfaces));
    }

    /**
     * 获取泛型的实际类型
     *
     * @throws NoSuchFieldException -
     */
    private static void test1() throws NoSuchFieldException {
        ResolvableType fieldType = ResolvableType.forField(GenericClass.class.getDeclaredField("string2IntegerListMap"));

        // 索引位置从0开始

        ResolvableType generic0 = fieldType.getGeneric(0);
        log.info("获取泛型的实际类型：Map<String, List<Integer>>中的String => {}", generic0);

        ResolvableType generic1 = fieldType.getGeneric(1);
        log.info("获取泛型的实际类型：Map<String, List<Integer>>中的List<Integer> => {}", generic1);

        ResolvableType generic10 = fieldType.getGeneric(1, 0);
        log.info("获取泛型的实际类型：Map<String, List<Integer>>中的Integer => {}", generic10);
    }

    /**
     * 获取泛型数组的元素类型
     *
     * @throws NoSuchFieldException -
     */
    private static void test0() throws NoSuchFieldException {
        ResolvableType fieldType = ResolvableType.forField(GenericClass.class.getDeclaredField("integerArray"));
        ResolvableType componentType = fieldType.getComponentType();
        log.info("获取泛型数组的元素类型：Integer[] => {}", componentType);
    }
}
